home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 026-050 / 042 / mg1a / buffer.c < prev    next >
C/C++ Source or Header  |  1995-03-13  |  14KB  |  553 lines

  1. /*
  2.  *        Buffer handling.
  3.  */
  4. #include    "def.h"
  5.  
  6. /*
  7.  * Attach a buffer to a window. The
  8.  * values of dot and mark come from the buffer
  9.  * if the use count is 0. Otherwise, they come
  10.  * from some other window.
  11.  */
  12. /*ARGSUSED*/
  13. usebuffer(f, n, k) {
  14.     register BUFFER    *bp;
  15.     register int    s;
  16.     char        bufn[NBUFN];
  17.  
  18.     /* Get buffer to use from user */
  19.     if (curbp->b_altb != NULL)
  20.         s=eread("Switch to buffer: (default %s) ", bufn, NBUFN,
  21.              EFNEW|EFBUF, 
  22. #ifdef    VARARGS
  23.              curbp->b_altb->b_bname
  24. #else
  25.              &(curbp->b_altb->b_bname), (char *) NULL
  26. #endif
  27.              ) ;
  28.     else
  29.         s=eread("Switch to buffer: ", bufn, NBUFN, EFNEW|EFBUF
  30. #ifndef VARARGS
  31.              ,(char *) NULL
  32. #endif
  33.              );
  34.     if (s == ABORT) return (s);
  35.     if (s == FALSE && curbp->b_altb != NULL) bp = curbp->b_altb ;
  36.     else if ((bp=bfind(bufn, TRUE)) == NULL) return (FALSE);
  37.  
  38.     /* and put it in current window */
  39.     curbp = bp;
  40.     return showbuffer(bp, curwp, WFFORCE|WFHARD);
  41. }
  42.  
  43. /*
  44.  * pop to buffer asked for by the user.
  45.  */
  46. /*ARGSUSED*/
  47. poptobuffer(f, n, k) {
  48.     register BUFFER    *bp;
  49.     register WINDOW    *wp;
  50.     register int    s;
  51.     char        bufn[NBUFN];
  52.  
  53.     /* Get buffer to use from user */
  54.     if (curbp->b_altb != NULL)
  55.         s=eread("Switch to buffer in other window: (default %s) ",
  56.              bufn, NBUFN, EFNEW|EFBUF, 
  57. #ifdef    VARARGS
  58.              curbp->b_altb->b_bname
  59. #else
  60.              &(curbp->b_altb->b_bname) ,(char *) NULL
  61. #endif
  62.              ) ;
  63.     else
  64.         s=eread("Switch to buffer in other window: ", bufn, NBUFN,
  65.         EFNEW|EFBUF
  66. #ifndef VARARGS
  67.         , (char *) NULL
  68. #endif
  69.         ) ;
  70.     if (s == ABORT) return (s);
  71.     if (s == FALSE && curbp->b_altb != NULL) bp = curbp->b_altb ;
  72.     else if ((bp=bfind(bufn, TRUE)) == NULL) return (FALSE);
  73.  
  74.     /* and put it in a new window */
  75.     if ((wp = popbuf(bp)) == NULL) return FALSE;
  76.     curbp = bp;
  77.     curwp = wp;
  78.     return TRUE;
  79. }
  80.  
  81. /*
  82.  * Dispose of a buffer, by name.
  83.  * Ask for the name. Look it up (don't get too
  84.  * upset if it isn't there at all!). Clear the buffer (ask
  85.  * if the buffer has been changed). Then free the header
  86.  * line and the buffer header. Bound to "C-X K".
  87.  */
  88. /*ARGSUSED*/
  89. killbuffer(f, n, k) {
  90.     register BUFFER    *bp;
  91.     register BUFFER    *bp1;
  92.     register BUFFER    *bp2;
  93.     register WINDOW    *wp;
  94.     register int    s;
  95.     char        bufn[NBUFN];
  96.  
  97.     if ((s=eread("Kill buffer: (default %s) ", bufn, NBUFN, EFNEW|EFBUF,
  98. #ifdef    VARARGS
  99.             curbp->b_bname
  100. #else
  101.             &(curbp->b_bname)
  102. #endif
  103.             )) == ABORT) return (s);
  104.     else if (s == FALSE) bp = curbp ;
  105.     else if ((bp=bfind(bufn, FALSE)) == NULL) return FALSE;
  106.  
  107.     if (bp->b_nwnd != 0) {
  108.         if ((bp1 = bp->b_altb) == NULL) return FALSE;
  109.         if (bclear(bp) != TRUE) return TRUE;
  110.         for (wp = wheadp; bp->b_nwnd > 0; wp = wp->w_wndp) {
  111.             /* Special case - could use showbuf, but don't */
  112.             if (wp->w_bufp == bp) {
  113.                 --bp->b_nwnd;
  114.                 ++bp1->b_nwnd;
  115.                 wp->w_bufp  = bp1 ;
  116.                 wp->w_dotp  = bp1->b_dotp;
  117.                 wp->w_doto  = bp1->b_doto;
  118.                 wp->w_markp = bp1->b_markp;
  119.                 wp->w_marko = bp1->b_marko;
  120.                 wp->w_linep = bp1->b_linep;
  121.                 wp->w_flag |= WFMODE|WFFORCE|WFHARD;
  122.             }
  123.         }
  124.     }
  125.     else if (bclear(bp) != TRUE) return TRUE;
  126.     if (bp == curbp) curbp = bp->b_altb;
  127.     free((char *) bp->b_linep);        /* Release header line.    */
  128.     bp1 = NULL;                /* Find the header.    */
  129.     bp2 = bheadp;
  130.     while (bp2 != bp) {
  131.         if (bp2->b_altb == bp) 
  132.             bp2->b_altb = (bp->b_altb == bp2) ? NULL : bp->b_altb;
  133.         bp1 = bp2;
  134.         bp2 = bp2->b_bufp;
  135.     }
  136.     bp2 = bp2->b_bufp;            /* Next one in chain.    */
  137.     if (bp1 == NULL)            /* Unlink it.        */
  138.         bheadp = bp2;
  139.     else
  140.         bp1->b_bufp = bp2;
  141.     while (bp2 != NULL) {            /* Finish with altb's    */
  142.         if (bp2->b_altb == bp) 
  143.             bp2->b_altb = (bp->b_altb == bp2) ? NULL : bp->b_altb;
  144.         bp2 = bp2->b_bufp;
  145.     }
  146.     free(bp->b_bname);        /* Release name block    */
  147.     free((char *) bp);            /* Release buffer block    */
  148.     return (TRUE);
  149. }
  150.  
  151. /*
  152.  * Save some buffers - just call anycb with the arg flag.
  153.  */
  154. /*ARGSUSED*/
  155. savebuffers(f, n, k) {
  156.     if (anycb(f) == ABORT) return ABORT;
  157.     return TRUE;
  158. }
  159.  
  160. /*
  161.  * Display the buffer list. This is done
  162.  * in two parts. The "makelist" routine figures out
  163.  * the text, and puts it in a buffer. "popbuf"
  164.  * then pops the data onto the screen. Bound to
  165.  * "C-X C-B".
  166.  */
  167. /*ARGSUSED*/
  168. listbuffers(f, n, k) {
  169.     register BUFFER    *bp;
  170.     register WINDOW *wp;
  171.     BUFFER         *makelist();
  172.     WINDOW        *popb();
  173.  
  174.     if ((bp=makelist()) == NULL || (wp=popbuf(bp)) == NULL)
  175.         return FALSE;
  176.     wp->w_dotp = bp->b_dotp;    /* fix up if window already on screen */
  177.     wp->w_doto = bp->b_doto;
  178.     return TRUE;
  179. }
  180.  
  181. /*
  182.  * This routine rebuilds the text for the
  183.  * list buffers command. Return TRUE if
  184.  * everything works. Return FALSE if there
  185.  * is an error (if there is no memory).
  186.  */
  187. BUFFER *
  188. makelist() {
  189.     register char    *cp1;
  190.     register char    *cp2;
  191.     register int    c;
  192.     register BUFFER    *bp;
  193.     register LINE    *lp;
  194.     register RSIZE    nbytes;
  195.     BUFFER        *blp;
  196.     char        b[6+1];
  197.     char        line[128];
  198.     
  199.     if ((blp = bfind("*Buffer List*", TRUE)) == NULL) return NULL;
  200.     if (bclear(blp) != TRUE) return NULL;
  201.     blp->b_flag &= ~BFCHG;            /* Blow away old.    */
  202.  
  203.     (VOID) strcpy(line, " MR Buffer");
  204.     cp1 = line + 10;
  205.     while(cp1 < line + 4 + NBUFN + 1) *cp1++ = ' ';
  206.     (VOID) strcpy(cp1, "Size   File");
  207.     if (addline(blp, line) == FALSE) return NULL;
  208.     (VOID) strcpy(line, " -- ------");
  209.     cp1 = line + 10;
  210.     while(cp1 < line + 4 + NBUFN + 1) *cp1++ = ' ';
  211.     (VOID) strcpy(cp1, "----   ----");
  212.     if (addline(blp, line) == FALSE) return NULL;
  213.     bp = bheadp;                /* For all buffers    */
  214.     while (bp != NULL) {
  215.         cp1 = &line[0];            /* Start at left edge    */
  216.         *cp1++ = (bp == curbp) ? '.' : ' ';
  217.         *cp1++ = ((bp->b_flag&BFCHG) != 0) ? '*' : ' ';
  218.         *cp1++ = ' ';            /* Gap.            */
  219.         *cp1++ = ' ';
  220.         cp2 = &bp->b_bname[0];        /* Buffer name        */
  221.         while ((c = *cp2++) != 0)
  222.             *cp1++ = c;
  223.         while (cp1 < &line[4+NBUFN+1])
  224.             *cp1++ = ' ';        
  225.         nbytes = 0;            /* Count bytes in buf.    */
  226.         if (bp != blp) {
  227.             lp = lforw(bp->b_linep);
  228.             while (lp != bp->b_linep) {
  229.                 nbytes += llength(lp)+1;
  230.                 lp = lforw(lp);
  231.             }
  232.         }
  233.         (VOID) itor(b, 6, nbytes);    /* 6 digit buffer size.    */
  234.         cp2 = &b[0];
  235.         while ((c = *cp2++) != 0)
  236.             *cp1++ = c;
  237.         *cp1++ = ' ';            /* Gap..            */
  238.         cp2 = &bp->b_fname[0];        /* File name        */
  239.         if (*cp2 != 0) {
  240.             while ((c = *cp2++) != 0) {
  241.                 if (cp1 < &line[128-1])
  242.                     *cp1++ = c;
  243.             }
  244.         }
  245.         *cp1 = 0;            /* Add to the buffer.    */
  246.         if (addline(blp, line) == FALSE)
  247.             return NULL;
  248.         bp = bp->b_bufp;
  249.     }
  250.     blp->b_dotp = lforw(blp->b_linep);    /* put dot at beginning of buffer */
  251.     blp->b_doto = 0;
  252.     return blp;                /* All done        */
  253. }
  254.  
  255. /*
  256.  * Used above.
  257.  */
  258. static itor(buf, width, num)
  259. register char buf[]; register int width; register RSIZE num; {
  260.     register RSIZE r;
  261.  
  262.     if (num / 10 == 0) {
  263.         buf[0] = (num % 10) + '0';
  264.         for (r = 1; r < width; buf[r++] = ' ')
  265.             ;
  266.         buf[width] = '\0';
  267.         return 1;
  268.     } else {
  269.         buf[r = itor(buf, width, num / (RSIZE)10)] = 
  270.                 (num % (RSIZE)10) + '0';
  271.         return r + 1;
  272.     }
  273. }
  274.  
  275. /*
  276.  * The argument "text" points to
  277.  * a string. Append this line to the
  278.  * buffer. Handcraft the EOL
  279.  * on the end. Return TRUE if it worked and
  280.  * FALSE if you ran out of room.
  281.  */
  282. addline(bp, text) register BUFFER *bp; char *text; {
  283.     register LINE    *lp;
  284.     register int    i;
  285.     register int    ntext;
  286.  
  287.     ntext = strlen(text);
  288.     if ((lp=lalloc((RSIZE) ntext)) == NULL)
  289.         return (FALSE);
  290.     for (i=0; i<ntext; ++i)
  291.         lputc(lp, i, text[i]);
  292.     bp->b_linep->l_bp->l_fp = lp;        /* Hook onto the end    */
  293.     lp->l_bp = bp->b_linep->l_bp;
  294.     bp->b_linep->l_bp = lp;
  295.     lp->l_fp = bp->b_linep;
  296.     if (bp->b_dotp == bp->b_linep)        /* If "." is at the end    */
  297.         bp->b_dotp = lp;        /* move it to new line    */
  298.     if (bp->b_markp == bp->b_linep)        /* ditto for mark     */
  299.         bp->b_markp = lp;
  300.     return (TRUE);
  301. }
  302.  
  303. /*
  304.  * Look through the list of buffers, giving the user
  305.  * a chance to save them.  Return TRUE if there are
  306.  * any changed buffers afterwards. Buffers that don't
  307.  * have an associated file don't count. Return FALSE
  308.  * if there are no changed buffers.
  309.  */
  310. anycb(f) {
  311.     register BUFFER    *bp;
  312.     register int    s = FALSE, save = FALSE;
  313.     char        prompt[NFILEN + 11];
  314.  
  315.     for (bp = bheadp; bp != NULL; bp = bp->b_bufp) {
  316.         if (*(bp->b_fname) != '\0'
  317.         &&  (bp->b_flag&BFCHG) != 0) {
  318.             (VOID) strcpy(prompt, "Save file ");
  319.             (VOID) strcpy(prompt + 10, bp->b_fname);
  320.             if ((f == TRUE || (save = eyorn(prompt)) == TRUE)
  321.             &&  writeout(bp, bp->b_fname) == TRUE) {
  322.                 bp->b_flag &= ~BFCHG;
  323.                 upmodes(bp);
  324.             } else s = TRUE;
  325.             if (save == ABORT) return (save);
  326.             save = TRUE;
  327.         }
  328.     }
  329.     if (save == FALSE && kbdmop == NULL)
  330.         ewprintf("(No files need saving)");
  331.     return s;
  332. }
  333.  
  334. /*
  335.  * Search for a buffer, by name.
  336.  * If not found, and the "cflag" is TRUE,
  337.  * create a buffer and put it in the list of
  338.  * all buffers. Return pointer to the BUFFER
  339.  * block for the buffer.
  340.  */
  341. BUFFER    *
  342. bfind(bname, cflag) register char *bname; {
  343.     register BUFFER    *bp;
  344.     char        *malloc();
  345.     register LINE    *lp;
  346.  
  347.     bp = bheadp;
  348.     while (bp != NULL) {
  349.         if (strcmp(bname, bp->b_bname) == 0)
  350.             return (bp);
  351.         bp = bp->b_bufp;
  352.     }
  353.     if (cflag!=TRUE) return NULL;
  354.     /*NOSTRICT*/
  355.     if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL) {
  356.         ewprintf("Can't get %d bytes", sizeof(BUFFER));
  357.         return NULL;
  358.     }
  359.     if ((bp->b_bname=malloc(strlen(bname)+1)) == NULL) {
  360.         ewprintf("Can't get %d bytes", strlen(bname)+1);
  361.         free((char *) bp);
  362.         return NULL;
  363.     }
  364.     if ((lp=lalloc((RSIZE) 0)) == NULL) {
  365.         free(bp->b_bname);
  366.         free((char *) bp);
  367.         return NULL;
  368.     }
  369.     bp->b_altb = bp->b_bufp  = NULL;
  370.     bp->b_dotp  = lp;
  371.     bp->b_doto  = 0;
  372.     bp->b_markp = NULL;
  373.     bp->b_marko = 0;
  374.     bp->b_flag  = 0;
  375.     bp->b_nwnd  = 0;
  376.     bp->b_linep = lp;
  377.     (VOID) strcpy(bp->b_fname, "");
  378.     (VOID) strcpy(bp->b_bname, bname);
  379.     lp->l_fp = lp;
  380.     lp->l_bp = lp;
  381.     bp->b_bufp = bheadp;
  382.     bheadp = bp;
  383.     return (bp);
  384. }
  385.  
  386. /*
  387.  * This routine blows away all of the text
  388.  * in a buffer. If the buffer is marked as changed
  389.  * then we ask if it is ok to blow it away; this is
  390.  * to save the user the grief of losing text. The
  391.  * window chain is nearly always wrong if this gets
  392.  * called; the caller must arrange for the updates
  393.  * that are required. Return TRUE if everything
  394.  * looks good.
  395.  */
  396. bclear(bp) register BUFFER *bp; {
  397.     register LINE    *lp;
  398.     register int    s;
  399.     
  400.     if ((bp->b_flag&BFCHG) != 0        /* Changed.        */
  401.     && (s=eyesno("Buffer modified; kill anyway")) != TRUE)
  402.         return (s);
  403.     bp->b_flag  &= ~BFCHG;            /* Not changed        */
  404.     while ((lp=lforw(bp->b_linep)) != bp->b_linep)
  405.         lfree(lp);
  406.     bp->b_dotp  = bp->b_linep;        /* Fix "."        */
  407.     bp->b_doto  = 0;
  408.     bp->b_markp = NULL;            /* Invalidate "mark"    */
  409.     bp->b_marko = 0;
  410.     return (TRUE);
  411. }
  412.  
  413. /*
  414.  * Display the given buffer in the given window. Flags indicated
  415.  * action on redisplay.
  416.  */
  417. showbuffer(bp, wp, flags) register BUFFER *bp; register WINDOW *wp; {
  418.     register BUFFER    *obp;
  419.     register WINDOW    *owp;
  420.  
  421.     if (wp->w_bufp == bp) {            /* Easy case!    */
  422.         wp->w_flag |= flags;
  423.         return TRUE ;
  424.     }
  425.  
  426.     /* First, dettach the old buffer from the window */
  427.     if ((bp->b_altb = obp = wp->w_bufp) != NULL) {
  428.         if (--obp->b_nwnd == 0) {
  429.             obp->b_dotp  = wp->w_dotp;
  430.             obp->b_doto  = wp->w_doto;
  431.             obp->b_markp = wp->w_markp;
  432.             obp->b_marko = wp->w_marko;
  433.         }
  434.     }
  435.  
  436.     /* Now, attach the new buffer to the window */
  437.     wp->w_bufp = bp;
  438.  
  439.     if (bp->b_nwnd++ == 0) {        /* First use.        */
  440.         wp->w_dotp  = bp->b_dotp;
  441.         wp->w_doto  = bp->b_doto;
  442.         wp->w_markp = bp->b_markp;
  443.         wp->w_marko = bp->b_marko;
  444.     } else
  445.     /* already on screen, steal values from other window */
  446.         for (owp = wheadp; owp != NULL; owp = wp->w_wndp)
  447.             if (wp->w_bufp == bp && owp != wp) {
  448.                 wp->w_dotp  = owp->w_dotp;
  449.                 wp->w_doto  = owp->w_doto;
  450.                 wp->w_markp = owp->w_markp;
  451.                 wp->w_marko = owp->w_marko;
  452.                 break;
  453.             }
  454.     wp->w_flag |= WFMODE|flags;
  455.     return TRUE;
  456. }
  457.  
  458. /*
  459.  * Pop the buffer we got passed onto the screen.
  460.  * Returns a status.
  461.  */
  462. WINDOW *
  463. popbuf(bp) register BUFFER *bp; {
  464.     register WINDOW    *wp;
  465.  
  466.     if (bp->b_nwnd == 0) {        /* Not on screen yet.    */
  467.         if ((wp=wpopup()) == NULL) return NULL;
  468.     } else
  469.         for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
  470.             if (wp->w_bufp == bp) {
  471.                 wp->w_flag |= WFHARD|WFFORCE;
  472.                 return wp ;
  473.             }
  474.     if (showbuffer(bp, wp, WFHARD) != TRUE) return NULL;
  475.     return wp;
  476. }
  477.  
  478. /*
  479.  * Insert another buffer at dot.  Very useful.
  480.  */
  481.  
  482. bufferinsert(f, n, k)
  483. {
  484.     register BUFFER *bp;
  485.     register LINE    *clp;
  486.     register int    clo;
  487.     register int    nline;
  488.     int        s;
  489.     char        bufn[NBUFN];
  490.  
  491.     /* Get buffer to use from user */
  492.     if (curbp->b_altb != NULL)
  493.         s=eread("Insert buffer: (default %s) ", bufn, NBUFN,
  494.              EFNEW|EFBUF, &(curbp->b_altb->b_bname),
  495.              (char *) NULL) ;
  496.     else
  497.         s=eread("Insert buffer: ", bufn, NBUFN, EFNEW|EFBUF,
  498.              (char *) NULL) ;
  499.     if (s == ABORT) return (s);
  500.     if (s == FALSE && curbp->b_altb != NULL) bp = curbp->b_altb;
  501.     else if ((bp=bfind(bufn, FALSE)) == NULL) return (FALSE);
  502.  
  503.     if (bp==curbp) {
  504.         ewprintf("Cannot insert buffer into self");
  505.         return (FALSE);
  506.     }
  507.  
  508.     /* insert the buffer */    
  509.     nline = 0;
  510.     for (clp = lforw(bp->b_linep); clp != bp->b_linep; clp = lforw(clp)) {
  511.         for (clo = 0; clo < llength(clp); clo++)
  512.             if (linsert((RSIZE)1, lgetc(clp, clo)) == FALSE)
  513.                 return (FALSE);
  514.         if (newline(FALSE, 1, KRANDOM) == FALSE) /* fake newline */
  515.             return (FALSE);
  516.         nline++;
  517.     }
  518.     if (kbdmop==NULL) {
  519.         if (nline == 1)
  520.             ewprintf("[Inserted 1 line]");
  521.         else
  522.             ewprintf("[Inserted %d lines]", nline);
  523.     }
  524.  
  525.     clp = curwp->w_linep;            /* cosmetic adjustment */
  526.     if (curwp->w_dotp == clp) {        /* for offscreen insert */
  527.         while (nline-- && lback(clp)!=curbp->b_linep)
  528.             clp = lback(clp);
  529.         curwp->w_linep = clp;        /* adjust framing.    */
  530.         curwp->w_flag |= WFHARD;
  531.     }
  532.     return (TRUE);
  533. }
  534.  
  535. /*
  536.  * Turn off the dirty bit on this buffer.
  537.  */
  538. /*ARGSUSED*/
  539. notmodified(f, n, k)
  540. {
  541.     register WINDOW *wp;
  542.     
  543.     curbp->b_flag &= ~BFCHG;
  544.     wp = wheadp;                /* Update mode lines.    */
  545.     while (wp != NULL) {
  546.         if (wp->w_bufp == curbp)
  547.             wp->w_flag |= WFMODE;
  548.         wp = wp->w_wndp;
  549.     }
  550.     ewprintf("Modification-flag cleared");
  551.     return (TRUE);
  552. }
  553.